home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Crypt / Xtea.php < prev    next >
PHP Script  |  2004-03-24  |  15KB  |  475 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. //
  4. // +----------------------------------------------------------------------+
  5. // | PHP version 4.0                                                      |
  6. // +----------------------------------------------------------------------+
  7. // | Copyright (c) 2002 The PHP Group                                     |
  8. // +----------------------------------------------------------------------+
  9. // | This source file is subject to version 2.02 of the PHP license,      |
  10. // | that is bundled with this package in the file LICENSE, and is        |
  11. // | available at through the world-wide-web at                           |
  12. // | http://www.php.net/license/2_02.txt.                                 |
  13. // | If you did not receive a copy of the PHP license and are unable to   |
  14. // | obtain it through the world-wide-web, please send a note to          |
  15. // | license@php.net so we can mail you a copy immediately.               |
  16. // +----------------------------------------------------------------------+
  17. // | Authors: Jeroen Derks <jeroen@derks.it>                              |
  18. // +----------------------------------------------------------------------+
  19. // | Original code: http://vader.brad.ac.uk/tea/source.shtml#new_ansi     |
  20. // +----------------------------------------------------------------------+
  21. //
  22. // $Id: Xtea.php,v 1.6 2002/09/03 11:04:08 jeroend Exp $
  23. //
  24.  
  25. /** PEAR base class */
  26. require_once 'PEAR.php';
  27.  
  28. /**
  29.  *  Class that implements the xTEA encryption algorithm.
  30.  *  This enables you to encrypt data without requiring mcrypt.
  31.  *
  32.  *  From the C source:
  33.  *  -----------------------------------------
  34.  *  The Tiny Encryption Algorithm (TEA) by
  35.  *  David Wheeler and Roger Needham of the
  36.  *  Cambridge Computer Laboratory.
  37.  *
  38.  *  Placed in the Public Domain by
  39.  *  David Wheeler and Roger Needham.
  40.  *
  41.  *  **** ANSI C VERSION (New Variant) ****
  42.  *
  43.  *  Notes:
  44.  *
  45.  *  TEA is a Feistel cipher with XOR and
  46.  *  and addition as the non-linear mixing
  47.  *  functions.
  48.  *
  49.  *  Takes 64 bits of data in v[0] and v[1].
  50.  *  Returns 64 bits of data in w[0] and w[1].
  51.  *  Takes 128 bits of key in k[0] - k[3].
  52.  *
  53.  *  TEA can be operated in any of the modes
  54.  *  of DES. Cipher Block Chaining is, for example,
  55.  *  simple to implement.
  56.  *
  57.  *  n is the number of iterations. 32 is ample,
  58.  *  16 is sufficient, as few as eight may be OK.
  59.  *  The algorithm achieves good dispersion after
  60.  *  six iterations. The iteration count can be
  61.  *  made variable if required.
  62.  *
  63.  *  Note this is optimised for 32-bit CPUs with
  64.  *  fast shift capabilities. It can very easily
  65.  *  be ported to assembly language on most CPUs.
  66.  *
  67.  *  delta is chosen to be the real part of (the
  68.  *  golden ratio Sqrt(5/4) - 1/2 ~ 0.618034
  69.  *  multiplied by 2^32).
  70.  *
  71.  *  This version has been amended to foil two
  72.  *  weaknesses identified by David A. Wagner
  73.  *  (daw@cs.berkeley.edu): 1) effective key
  74.  *  length of old-variant TEA was 126 not 128
  75.  *  bits 2) a related key attack was possible
  76.  *  although impractical.
  77.  *
  78.  *  void encipher(unsigned long *const v,unsigned long *const w,
  79.  *  const unsigned long *const k)
  80.  *  {
  81.  *   register unsigned long       y=v[0],z=v[1],sum=0,delta=0x9E3779B9,n=32;
  82.  *
  83.  *   while(n-->0)
  84.  *      {
  85.  *        y+= (z<<4 ^ z>>5) + z ^ sum + k[sum&3];
  86.  *      sum += delta;
  87.  *      z+= (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 & 3];
  88.  *      }
  89.  *
  90.  *   w[0]=y; w[1]=z;
  91.  *  }
  92.  *
  93.  *  void decipher(unsigned long *const v,unsigned long *const w,
  94.  *  const unsigned long *const k)
  95.  *  {
  96.  *   register unsigned long       y=v[0],z=v[1],sum=0xC6EF3720,
  97.  *                                delta=0x9E3779B9,n=32;
  98.  *
  99.  *   # sum = delta<<5, in general sum = delta * n
  100.  *
  101.  *       while(n-->0)
  102.  *          {
  103.  *            z-= (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 & 3];
  104.  *          sum -= delta;
  105.  *            y-= (z<<4 ^ z>>5) + z ^ sum + k[sum&3];
  106.  *          }
  107.  *
  108.  *   w[0]=y; w[1]=z;
  109.  *  }
  110.  *
  111.  *  -----------------------------------------
  112.  *
  113.  *  @TODO       Add CFB.
  114.  *
  115.  *  @package    Crypt
  116.  *  @version    $Revision: 1.6 $
  117.  *  @access     public
  118.  *  @author     Jeroen Derks <jeroen@derks.it>
  119.  */
  120.  
  121. class Crypt_Xtea extends PEAR {
  122.  
  123.     /**
  124.      *  Number of iterations.
  125.      *  @var    integer
  126.      *  @access private
  127.      */
  128.     var $n_iter;
  129.  
  130.     // {{{ Crypt_Xtea()
  131.  
  132.     /**
  133.      *  Constructor, sets the number of iterations.
  134.      *
  135.      *  @access public
  136.      *  @author         Jeroen Derks <jeroen@derks.it>
  137.      *  @see            setIter()
  138.      */
  139.     function Crypt_Xtea() {
  140.         $this->setIter( 32 );
  141.     }
  142.  
  143.     // }}}
  144.     // {{{ setIter()
  145.  
  146.     /**
  147.      *  Set the number of iterations to use.
  148.      *
  149.      *  @param  integer $n_iter Number of iterations to use.
  150.      *
  151.      *  @access public
  152.      *  @author         Jeroen Derks <jeroen@derks.it>
  153.      *  @see            getIter()
  154.      */
  155.     function setIter( $n_iter ) {
  156.         $this->n_iter = $n_iter;
  157.     }
  158.  
  159.     // }}}
  160.     // {{{ getIter()
  161.  
  162.     /**
  163.      *  Get the number of iterations to use.
  164.      *
  165.      *  @return integer Number of iterations to use.
  166.      *
  167.      *  @access public
  168.      *  @author         Jeroen Derks <jeroen@derks.it>
  169.      *  @see            getIter()
  170.      */
  171.     function getIter() {
  172.         return $this->n_iter;
  173.     }
  174.  
  175.     // }}}
  176.     // {{{ encrypt()
  177.  
  178.     /**
  179.      *  Encrypt a string using a specific key.
  180.      *
  181.      *  @param  string  $data   Data to encrypt.
  182.      *  @param  string  $key    Key to encrypt data with (binary string).
  183.      *
  184.      *  @return string          Binary encrypted character string.
  185.      *
  186.      *  @access public
  187.      *  @author         Jeroen Derks <jeroen@derks.it>
  188.      *  @see            Decrypt(), _EncipherLong(), _Resize(), _str2long()
  189.      */
  190.     function encrypt($data, $key) {
  191.         // resize data to 32 bits (4 bytes)
  192.         $n = $this->_resize($data, 4);
  193.  
  194.         // convert data to long
  195.         $data_long[0]    = $n;
  196.         $n_data_long    = $this->_str2long(1, $data, $data_long);
  197.  
  198.         // resize data_long to 64 bits (2 longs of 32 bits)
  199.         $n = count($data_long);
  200.         if (($n & 1) == 1) {
  201.             $data_long[$n] = chr(0);
  202.             $n_data_long++;
  203.         }
  204.  
  205.         // resize key to a multiple of 128 bits (16 bytes)
  206.         $this->_resize($key, 16, true);
  207.  
  208.         // convert key to long
  209.         $n_key_long = $this->_str2long(0, $key, $key_long);
  210.  
  211.         // encrypt the long data with the key
  212.         $enc_data   = '';
  213.         $w          = array( 0, 0 );
  214.         $j          = 0;
  215.         $k          = array( 0, 0, 0, 0 );
  216.         for ($i = 0; $i < $n_data_long; ++$i) {
  217.             // get next key part of 128 bits
  218.             if ($j + 4 <= $n_key_long) {
  219.                 $k[0] = $key_long[$j];
  220.                 $k[1] = $key_long[$j + 1];
  221.                 $k[2] = $key_long[$j + 2];
  222.                 $k[3] = $key_long[$j + 3];
  223.             } else {
  224.                 $k[0] = $key_long[$j % $n_key_long];
  225.                 $k[1] = $key_long[($j + 1) % $n_key_long];
  226.                 $k[2] = $key_long[($j + 2) % $n_key_long];
  227.                 $k[3] = $key_long[($j + 3) % $n_key_long];
  228.             }
  229.             $j = ($j + 4) % $n_key_long;
  230.  
  231.             $this->_encipherLong($data_long[$i], $data_long[++$i], $w, $k);
  232.  
  233.             // append the enciphered longs to the result
  234.             $enc_data .= $this->_long2str($w[0]);
  235.             $enc_data .= $this->_long2str($w[1]);
  236.         }
  237.  
  238.         return $enc_data;
  239.     }
  240.  
  241.     // }}}
  242.     // {{{ decrypt()
  243.  
  244.     /**
  245.      *  Decrypt an encrypted string using a specific key.
  246.      *
  247.      *  @param  string  $data   Encrypted data to decrypt.
  248.      *  @param  string  $key    Key to decrypt encrypted data with (binary string).
  249.      *
  250.      *  @return string          Binary decrypted character string.
  251.      *
  252.      *  @access public
  253.      *  @author         Jeroen Derks <jeroen@derks.it>
  254.      *  @see            _EncipherLong(), Encrypt(), _Resize(), _str2long()
  255.      */
  256.     function decrypt($enc_data, $key) {
  257.         // convert data to long
  258.         $n_enc_data_long = $this->_str2long(0, $enc_data, $enc_data_long);
  259.  
  260.         // resize key to a multiple of 128 bits (16 bytes)
  261.         $this->_resize($key, 16, true);
  262.  
  263.         // convert key to long
  264.         $n_key_long = $this->_str2long(0, $key, $key_long);
  265.  
  266.         // decrypt the long data with the key
  267.         $data   = '';
  268.         $w      = array( 0, 0 );
  269.         $j      = 0;
  270.         $len    = 0;
  271.         $k      = array( 0, 0, 0, 0 );
  272.         $pos    = 0;
  273.         for ($i = 0; $i < $n_enc_data_long; $i += 2) {
  274.             // get next key part of 128 bits
  275.             if ($j + 4 <= $n_key_long) {
  276.                 $k[0] = $key_long[$j];
  277.                 $k[1] = $key_long[$j + 1];
  278.                 $k[2] = $key_long[$j + 2];
  279.                 $k[3] = $key_long[$j + 3];
  280.             } else {
  281.                 $k[0] = $key_long[$j % $n_key_long];
  282.                 $k[1] = $key_long[($j + 1) % $n_key_long];
  283.                 $k[2] = $key_long[($j + 2) % $n_key_long];
  284.                 $k[3] = $key_long[($j + 3) % $n_key_long];
  285.             }
  286.             $j = ($j + 4) % $n_key_long;
  287.  
  288.             $this->_decipherLong($enc_data_long[$i], $enc_data_long[$i + 1], $w, $k);
  289.  
  290.             // append the deciphered longs to the result data (remove padding)
  291.             if (0 == $i) {
  292.                 $len = $w[0];
  293.                 if (4 <= $len) {
  294.                     $data .= $this->_long2str($w[1]);
  295.                 } else {
  296.                     $data .= substr( $this->_long2str($w[1]), 0, $len % 4 );
  297.                 }
  298.             } else {
  299.                 $pos = ($i - 1) * 4;
  300.                 if ($pos + 4 <= $len) {
  301.                     $data .= $this->_long2str($w[0]);
  302.  
  303.                     if ($pos + 8 <= $len) {
  304.                         $data .= $this->_long2str($w[1]);
  305.                     } elseif ($pos + 4 < $len) {
  306.                         $data .= substr( $this->_long2str($w[1]), 0, $len % 4 );
  307.                     }
  308.                 } else {
  309.                     $data .= substr( $this->_long2str($w[0]), 0, $len % 4 );
  310.                 }
  311.             }
  312.         }
  313.         return $data;
  314.     }
  315.  
  316.     // }}}
  317.     // {{{ _encipherLong()
  318.  
  319.     /**
  320.      *  Encipher a single long (32-bit) value.
  321.      *
  322.      *  @param  integer $y  32 bits of data.
  323.      *  @param  integer $z  32 bits of data.
  324.      *  @param  array   &$w Placeholder for enciphered 64 bits (in w[0] and w[1]).
  325.      *  @param  array   &$k Key 128 bits (in k[0]-k[3]).
  326.      *
  327.      *  @access private
  328.      *  @author         Jeroen Derks <jeroen@derks.it>
  329.      *  @see            $n_iter, _DecipherLong()
  330.      */
  331.     function _encipherLong($y, $z, &$w, &$k) {
  332.         $sum    = (integer) 0;
  333.         $delta  = (integer) 0x9E3779B9;
  334.         $n      = (integer) $this->n_iter;
  335.  
  336.         while ($n-- > 0) {
  337.             $y      += ($z << 4 ^ $z >> 5) + $z ^ $sum + $k[$sum & 3];
  338.             $sum    += $delta;
  339.             $z      += ($y << 4 ^ $y >> 5) + $y ^ $sum + $k[$sum >> 11 & 3];
  340.         }
  341.  
  342.         $w[0] = $y & 0xffffffff;
  343.         $w[1] = $z & 0xffffffff;
  344.     }
  345.  
  346.     // }}}
  347.     // {{{ _decipherLong()
  348.  
  349.     /**
  350.      *  Decipher a single long (32-bit) value.
  351.      *
  352.      *  @param  integer $y  32 bits of enciphered data.
  353.      *  @param  integer $z  32 bits of enciphered data.
  354.      *  @param  array   &$w Placeholder for deciphered 64 bits (in w[0] and w[1]).
  355.      *  @param  array   &$k Key 128 bits (in k[0]-k[3]).
  356.      *
  357.      *  @access private
  358.      *  @author         Jeroen Derks <jeroen@derks.it>
  359.      *  @see            $n_iter, _DecipherLong()
  360.      */
  361.     function _decipherLong($y, $z, &$w, &$k) {
  362.         // sum = delta<<5, in general sum = delta * n
  363.         $sum    = (integer) 0xC6EF3720;
  364.         $delta  = (integer) 0x9E3779B9;
  365.         $n      = (integer) $this->n_iter;
  366.  
  367.         while ($n-- > 0) {
  368.             $z      -= ($y << 4 ^ $y >> 5) + $y ^ $sum + $k[$sum >> 11 & 3];
  369.             $sum    -= $delta;
  370.             $y      -= ($z << 4 ^ $z >> 5) + $z ^ $sum + $k[$sum & 3];
  371.         }
  372.  
  373.         $w[0] = $y & 0xffffffff;
  374.         $w[1] = $z & 0xffffffff;
  375.     }
  376.  
  377.     // }}}
  378.     // {{{ _resize()
  379.  
  380.     /**
  381.      *  Resize data string to a multiple of specified size.
  382.      *
  383.      *  @param  string  $data   Data string to resize to specified size.
  384.      *  @param  integer $size   Size in bytes to align data to.
  385.      *  @param  boolean $nonull Set to true if padded bytes should not be zero.
  386.      *
  387.      *  @return integer         Length of supplied data string.
  388.      *
  389.      *  @access private
  390.      *  @author         Jeroen Derks <jeroen@derks.it>
  391.      */
  392.     function _resize(&$data, $size, $nonull = false) {
  393.         $n = strlen($data);
  394.         $nmod = $n % $size;
  395.         if ($nmod > 0) {
  396.             if ($nonull) {
  397.                 for ($i = $n; $i < $n - $nmod + $size; ++$i) {
  398.                     $data[$i] = $data[$i % $n];
  399.                 }
  400.             } else {
  401.                 for ($i = $n; $i < $n - $nmod + $size; ++$i) {
  402.                     $data[$i] = chr(0);
  403.                 }
  404.             }
  405.         }
  406.         return $n;
  407.     }
  408.  
  409.     // }}}
  410.     // {{{ _hex2bin()
  411.  
  412.     /**
  413.      *  Convert a hexadecimal string to a binary string (e.g. convert "616263" to "abc").
  414.      *
  415.      *  @param  string  $str    Hexadecimal string to convert to binary string.
  416.      *
  417.      *  @return string          Binary string.
  418.      *
  419.      *  @access private
  420.      *  @author         Jeroen Derks <jeroen@derks.it>
  421.      */
  422.     function _hex2bin($str)
  423.     {
  424.         $len = strlen($str);
  425.         return pack("H" . $len, $str);
  426.     }
  427.  
  428.     // }}}
  429.     // {{{ _str2long()
  430.  
  431.     /**
  432.      *  Convert string to array of long.
  433.      *
  434.      *  @param  integer $start      Index into $data_long for output.
  435.      *  @param  string  &$data      Input string.
  436.      *  @param  array   &$data_long Output array of long.
  437.      *
  438.      *  @return integer             Index from which to optionally continue.
  439.      *
  440.      *  @access private
  441.      *  @author         Jeroen Derks <jeroen@derks.it>
  442.      */
  443.     function _str2long($start, &$data, &$data_long) {
  444.         $n = strlen($data);
  445.         for ($i = 0, $j = $start; $i < $n; $i = $i + 4, ++$j) {
  446.             $data_long[$j] = ((ord($data[$i]) & 0xff) << 24) +
  447.                              ((ord($data[$i + 1]) & 0xff) << 16) +
  448.                              ((ord($data[$i + 2]) & 0xff) << 8) +
  449.                              ((ord($data[$i + 3]) & 0xff));
  450.         }
  451.         return $j;
  452.     }
  453.  
  454.     // }}}
  455.     // {{{ _long2str()
  456.  
  457.     /**
  458.      *  Convert long to character string.
  459.      *
  460.      *  @param  long    $l  Long to convert to character string.
  461.      *
  462.      *  @return string      Character string.
  463.      *
  464.      *  @access private
  465.      *  @author         Jeroen Derks <jeroen@derks.it>
  466.      */
  467.     function _long2str($l) {
  468.         return pack( 'N', $l );
  469.     }
  470.  
  471.     // }}}
  472. }
  473.  
  474. ?>
  475.